<template>
  <div id="project-page">

    <div class="container">
      <div class="info-panel">
        <div class="left-info">
          <span><el-tag>项目名称：{{ curProject.name || '未知' }}</el-tag></span>
        </div>
        <span class="right-info">
          <span><el-tag type="success">成功：{{ successCnt }} / {{ tableData.length }}</el-tag></span>
          <span><el-tag type="danger">失败：{{ failCnt }} / {{ tableData.length }}</el-tag></span>
          <span><el-tag type="warning">执行中：{{ runningCnt }} / {{ tableData.length }}</el-tag></span>
          <span><el-tag type="info">未执行：{{ initCnt }} / {{ tableData.length }}</el-tag></span>
        </span>
      </div>
      <div
        class="controls-group"
        style="height: 90px; padding: 0 8px; display: flex; justify-content: flex-end; align-items: center;"
      >
        <div class="control" style="margin-right: auto;">
          <el-button icon="el-icon el-icon-monitor" type="success" @click="$router.push({name: 'home'})">
            返回项目列表
          </el-button>
        </div>
        <div class="control">
          <el-button-group>
            <el-button
              v-if="multipleSelection.length"
              icon="el-icon el-icon-magic-stick"
              type="danger"
              @click="handleBtnExecClick(multipleSelection.map(item => item.id))"
            >执行选中实例
            </el-button>
            <el-button
              v-if="multipleSelection.length"
              icon="el-icon el-icon-delete"
              type="danger"
              @click="handleBtnBatchDeleteClick"
            >删除选中实例
            </el-button>
            <el-button
              v-if="multipleSelection.length && multipleSelection.every(item => item.status === 1)"
              type="success"
            >统计选中实例
            </el-button>
            <el-button icon="el-icon el-icon-s-opportunity" type="success" @click="handleBtnSecDetailClick">调度详情
            </el-button>
            <el-button icon="el-icon el-icon-files" type="success" @click="handleBtnAdminClick">后台数据</el-button>
            <el-button icon="el-icon el-icon-plus" type="success" @click="handleBtnAddClick">添加新配置</el-button>
            <el-button icon="el-icon el-icon-loading" type="success" @click="fetchData">刷新</el-button>
          </el-button-group>
        </div>
      </div>
      <div class="table-con" style="margin: 0 8px; border: 1px solid #efefef; min-height: calc(100vh - 200px);">
        <el-table ref="main-table" :data="tableData" @selection-change="handleSelectionChange">
          <el-table-column align="center" type="selection" width="55"/>
          <el-table-column align="center" label="序号" type="index" width="55"/>
          <el-table-column align="center" label="执行命令" width="150">
            <template v-slot="scope">
              <div style="text-align: left;">
                {{ scope.row.command_str | overflowText(30) }}
                <el-tooltip :content="scope.row.command_str">
                  <i
                    class="el-icon el-icon-document-copy"
                    style="cursor: pointer;"
                    @click="handleIconCopyClick(scope.row.command_str)"
                  ></i>
                </el-tooltip>
              </div>
            </template>
          </el-table-column>
          <el-table-column sortable align="center" label="运行时间" prop="run_time"/>
          <el-table-column
            v-for="(v, k) in argsDict"
            align="center"
            :label="argsDict[k]"
          >
            <template v-slot="scope">
              {{ allArgsDict[scope.row.args.filter(id => allArgsDict[id].key === k)].desc | overflowText(250) }}
              <el-tooltip :content="allArgsDict[scope.row.args.filter(id => allArgsDict[id].key === k)].value">
                <i
                  class="el-icon el-icon-document-copy"
                  style="cursor: pointer;"
                  @click="handleIconCopyClick(allArgsDict[scope.row.args.filter(id => allArgsDict[id].key === k)].value)"
                ></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column sortable align="center" label="状态名称" prop="status_name"/>
          <el-table-column sortable align="center" label="创建时间" prop="add_time"/>
          <el-table-column sortable align="center" label="结束时间" prop="update_time"/>
          <el-table-column width="450px">
            <template v-slot="scope">
              <el-button-group v-if="scope.row.status !== 0 && scope.row.status !== 2">
                <el-button
                  icon="el-icon el-icon-view"
                  :type="scope.row.status === 1 ? 'success' : 'danger'"
                  @click="handleBtnDetailClick(scope.row)"
                >查看结果
                </el-button>
                <el-button
                  icon="el-icon el-icon-refresh-left"
                  :type="scope.row.status === 1 ? 'success' : 'danger'"
                  @click="handleBtnExecClick([scope.row.id])"
                >重新执行
                </el-button>
                <el-button
                  icon="el-icon el-icon-delete"
                  type="danger"
                  @click="handleBtnDeleteClick([scope.row.id])"
                >删除实例
                </el-button>
              </el-button-group>
              <el-button-group v-else>
                <el-button
                  icon="el-icon el-icon-magic-stick"
                  type="danger"
                  @click="handleBtnExecClick([scope.row.id])"
                >立即执行
                </el-button>
                <el-button
                  icon="el-icon el-icon-delete"
                  type="danger"
                  @click="handleBtnDeleteClick([scope.row.id])"
                >删除实例
                </el-button>
              </el-button-group>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>

    <command-adder
      ref="command-adder"
      :project="curProject"
      :visible.sync="isShowCommandAdder"
      @confirm="handleCommandAdderConfirm"
    />

  </div>
</template>

<script>
import _ from 'lodash'
import mixinTable from '@/mixins/mixin-table'
import api from '@/api'
import {copyTextToClipboard, Scheduler} from '@/lib/utils'
import CommandAdder from '@/views/benchmarks/components/CommandAdder'
import {CELERY_FLOWER_URL, DJANGO_ADMIN_URL} from '@/config/constant';

export default {
  name: "ProjectDetailPage",

  components: {CommandAdder},

  mixins: [mixinTable],

  props: ['projectId'],

  filters: {
    overflowText(val, len) {
      if (val.length > len) {
        return val.substring(0, len) + '...'
      }

      return val
    }
  },

  data() {
    return {
      // loading
      isLoading: false,

      // data
      allArgsDict: {},
      argsList: [],
      argsDict: {},
      curProject: {},
      curResult: '',

      // show flag
      isShowCommandAdder: false
    }
  },

  computed: {
    successCnt() {
      return this.tableData.filter(item => item.status === 1).length || 0
    },
    failCnt() {
      return this.tableData.filter(item => item.status === -1).length || 0
    },
    initCnt() {
      return this.tableData.filter(item => item.status === 0).length || 0
    },
    runningCnt() {
      return this.tableData.filter(item => item.status === 2).length || 0
    }
  },

  created() {
    this.fetchArgs()
    window.copyHandler = () => {
      this.handleIconCopyClick(this.curResult)
    }
  },

  methods: {
    fetchArgs() {
      api.options
         .list({})
         .then(({data}) => {
           this.argsList = (data.results || []).reduce((res, cur) => {
             this.$set(this.allArgsDict, cur.id, cur)
             if (res[cur.key]) {
               res[cur.key].push(cur)
             } else {
               this.$set(this.argsDict, cur.key, cur.key_name)
               res[cur.key] = [cur]
             }
             return res
           }, {})
         })
         .catch(err => {
           this.$message.error('获取参数失败')
         })
    },

    fetchData() {
      api.commands
         .list({project__id: this.projectId})
         .then(({data}) => {
           this.tableData = data.results || []
         })
         .catch(err => {
           this.tableData = []
           this.$message.error('网络错误')
         })

      api.projects
         .get({}, this.projectId)
         .then(({data}) => {
           this.curProject = data
         })
         .catch(err => {
           this.$message.error('项目信息异常')
           this.$router.push({name: 'home'})
         })
    },

    handleBtnBatchDeleteClick() {
      const promises = this.multipleSelection.map(data => {
        return api.commands
                  .rm({}, data.id)
      })

      Promise.all(promises)
             .then(res => {
               this.$message.success('删除完成！')
               this.fetchData()
             })
             .catch(err => {
               this.$message.error('删除失败！')
               this.fetchArgs()
             })
    },

    handleBtnDetailClick(data) {
      this.curResult = data.result
      this.$notify.info({
        title: '运算结果',
        duration: 0,
        dangerouslyUseHTMLString: true,
        message: `<i onclick="window.copyHandler()"
                    class="el-icon el-icon-document-copy"
                    style="cursor: pointer; position: absolute; left: 120px; top: 18px;">
                  </i>
                  <p style="overflow-y: auto; max-height: 400px;">${data.result.replace('\n', '<br>')}</p>`
      })
    },

    handleBtnDeleteClick(commandId) {
      if (commandId) {
        this.$confirm('此操作将永久删除该实例, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
            .then(() => {
              api.commands
                 .rm({}, commandId)
                 .then(res => {
                   this.$message.success('删除完成')
                   this.fetchData()
                 })
                 .catch(err => {
                   this.$message.error('删除失败')
                   this.fetchData()
                 })
            })
      }
    },

    handleCommandAdderConfirm(data) {
      // 生成所有的参数组合情况
      const argsHandler = (args) => {
        if (args.length === 1) {
          return args[0].map(item => [item])
        }
        if (args.length === 0) {
          return []
        }

        const res = []
        const childRes = argsHandler(args.slice(1))
        for (let i = 0; i < args[0].length; i++) {
          childRes.forEach(item => {
            const newRes = [args[0][i], ...item]
            res.push(newRes)
          })
        }

        return res
      }

      const allArgs = argsHandler(data.args)

      const loading = this.$loading({
        lock: true,
        text: '实例生成中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      // 稍微带点延迟访问接口，不然我的 sqlite 会上锁
      new Promise((resolve, reject) => {
        const resList = []
        allArgs.forEach((args, idx) => {
          setTimeout(() => {
            api.commands
               .create({...data, args})
               .then((res) => {
                 resList.push(true)
                 if (resList.length === allArgs.length) {
                   resolve(resList)
                 }
               })
               .catch(err => {
                 resList.push(false)
                 if (resList.length === allArgs.length) {
                   resolve(resList)
                 }
               })
          }, idx * 30)
        })
      })
        .then((res) => {
          loading.close()
          this.isShowCommandAdder = false
          this.fetchData()

          const failedCnt = res.reduce((cnt, success) => cnt + (success ? 0 : 1), 0)
          if (failedCnt === 0) {
            this.$message.success('实例全部创建完成')
          } else {
            this.$message.error(`有 ${failedCnt} 个实例创建失败了`)
          }
        })

    },

    handleIconCopyClick: _.throttle(function (text) {
      copyTextToClipboard(text)
      this.$message.success('复制完成')
    }, 1000),

    handleBtnSecDetailClick() {
      window.open(CELERY_FLOWER_URL)
    },

    handleBtnAdminClick() {
      window.open(DJANGO_ADMIN_URL)
    },

    handleBtnAddClick() {
      this.isShowCommandAdder = true
    },

    handleBtnExecClick(commandIds) {
      api.commands
         .runBatch({command_ids: commandIds})
         .then(res => {
           this.$refs['main-table'].clearSelection()
           this.$message.success('任务已发起')

           // 延时 1.5s 查询状态
           setTimeout(() => {
             this.fetchData()
           }, 1500)

           // 轮询查询状态
           const timer = setInterval(() => {
             this.fetchData()
             if (this.initCnt === 0) {
               clearInterval(timer)
             }
           }, 1000 * 6)
         })
         .catch(err => {
           console.log(err)
         })
    }
  }
}
</script>

<style lang="scss" scoped>
#project-page {
  .container {
    .info-panel {
      display: flex;
      justify-content: space-between;
      padding: 0 8px;

      .left-info {

      }

      .right-info {
        span + span {
          margin-left: 8px;
        }
      }
    }
  }
}
</style>
